<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Image Compression</title>
    <script src="./js/pica.min.js"></script>
    <script src="./js/pngquant.min.js"></script>
    <script src="./js/image-blob-reduce.min.js"></script>
    <script src="./js/browser-image-compressor.min.js"></script>
    <script src="./js/compressor.min.js"></script>
    <script src="./js/UPNG.min.js"></script>

    <style>
        #results img {
            width: 200px;
        }
    </style>
</head>

<body>
    <h1>Image Compression with Pica and pngquant</h1>
    <input type="file" id="upload" accept="image/*">
    <button onclick="compressImages()">Start Compression</button>
    <div id="results"></div>
    <script>
        var reducer = new window.ImageBlobReduce({
            pica: window.ImageBlobReduce.pica({ features: ['js', 'wasm', 'ww'] })
        });
        function compressImages() {
            const fileInput = document.getElementById('upload');
            if (fileInput.files.length === 0) {
                alert('Please select an image first.');
                return;
            }
            const file = fileInput.files[0];
            const img = new Image();
            img.src = URL.createObjectURL(file);

            img.onload = async function () {
                const canvas = document.createElement('canvas');
                const ctx = canvas.getContext('2d');
                canvas.width = img.width;
                canvas.height = img.height;
                ctx.drawImage(img, 0, 0);

                // Pica compression
                const pica1 = pica();
                const picaCanvas = document.createElement('canvas');
                picaCanvas.width = img.width;
                picaCanvas.height = img.height;

                try {
                    await pica1.resize(canvas, picaCanvas);
                    const picaBlob = await pica1.toBlob(picaCanvas, 'image/png', 0.8);
                    displayResult('Pica', picaBlob);
                } catch (error) {
                    console.error('Pica compression error:', error);
                }


                const reducerBlob = await reducer.toBlob(
                    file,
                    {
                        // max: 200,
                        // unsharpAmount: 80,
                        // unsharpRadius: 0.6,
                        // unsharpThreshold: 2
                    }
                )

                displayResult('ReducerBlob', reducerBlob);
                console.log(reducerBlob)

                // pngquant compression
                // try {
                //     const pngquantResult = await pngquant.compress(picaCanvas);
                //     const pngquantBlob = new Blob([pngquantResult.data], { type: 'image/png' });
                //     displayResult('pngquant', pngquantBlob);
                // } catch (error) {
                //     console.error('pngquant compression error:', error);
                // }


                new Imagemin(file, {
                    // maxWidth: Infinity,
                    // maxHeight: Infinity,
                    // minWidth: 0,
                    // minHeight: 0,
                    // maxSize: 200,
                    // quality: 0.9,
                    // checkOrientation: true,
                    // mimeType: '',

                    maxSizeMB: 1, // 设置压缩后的最大大小
                    useWebWorker: true, // 使用 Web Worker 进行压缩
                    initialQuality: 1, // 设置初始质量为1，确保无损压缩
                    fileType: 'image/png', // 确保文件类型为PNG
                    success(result) {
                        displayResult('Imagemin', result);
                    },
                    fail: error => { }
                })


                new Compressor(file, {
                    quality: 1,
                    success(result) {
                        console.log(result)
                        fileToBlob(result, (compressorBlob) => {
                            console.log('Compressor', compressorBlob);
                            displayResult('Compressor', compressorBlob);
                        });


                        // displayResult('Compressor', compressorBlob);

                        // const img = document.createElement('img');
                        // img.src = e.target.result;

                        // const sizeText = document.createElement('p');
                        // sizeText.textContent = `Compressor compressed size: ${result.size / 1024} kb，type: ${result.type}`;

                        // const resultsDiv = document.getElementById('results');
                        // resultsDiv.appendChild(sizeText);
                        // resultsDiv.appendChild(img);
                    },
                });

                const isPng = await isPNG(file);
                if (isPng) {
                    const upngFile = await compressPNGImage(file);
                    console.log('upngFile', upngFile)
                }
            };
        }

        function displayResult(method, blob) {
            const resultsDiv = document.getElementById('results');
            const url = URL.createObjectURL(blob);
            const img = document.createElement('img');
            img.src = url;

            const sizeText = document.createElement('p');
            sizeText.textContent = `${method} compressed size: ${blob.size / 1024} kb，type: ${blob.type}`;

            resultsDiv.appendChild(sizeText);
            resultsDiv.appendChild(img);
        }

        function fileToBlob(file, success) {
            console.log('fileToBlob', file)
            let reader = new FileReader();
            reader.addEventListener('load', (e) => {
                let base64 = e.target.result;
                let blob = new Blob([base64], { type: file.type });
                console.log("Blob对象", blob);
                success ? success(blob) : null;
            })
            reader.readAsDataURL(file)
        }

        async function compressPNGImage(file, ops = {}) {
            const { quality = 0.8, noCompressIfLarger = true } = ops;
            let { width, height } = ops;
            const arrayBuffer = await file.arrayBuffer();
            const decoded = UPNG.decode(arrayBuffer);
            const rgba8 = UPNG.toRGBA8(decoded);

            // 如果只指定了宽度或高度，则按比例缩放
            if (width && !height) {
                height = Math.round(decoded.height * (width / decoded.width));
            } else if (!width && height) {
                width = Math.round(decoded.width * (height / decoded.height));
            }

            // TODO：尺寸缩放，使用 canvas 先缩放

            width = width || decoded.width;
            height = height || decoded.height;

            const compressed = UPNG.encode(rgba8, width, height, 256 * quality);

            const newFile = new File([compressed], file.name || `${date.now()}.png`, { type: 'image/png' });

            if (!noCompressIfLarger) {
                return newFile;
            }

            return file.size > newFile.size ? newFile : file;
        }

        async function isPNG(file) {
            // 提取前8个字节
            const arraybuffer = await file.slice(0, 8).arrayBuffer();

            // PNG 的前8字节16进制表示
            const signature = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a];
            // const signature = [137, 80, 78, 71, 13, 10, 26, 10]

            // 转为 8位无符号整数数组 方便对比
            // https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array
            const source = new Uint8Array(arraybuffer);

            // 逐个字节对比
            for (let i = 0; i < signature.length; i++) {
                if (source[i] !== signature[i]) {
                    return false;
                }
            }
            return true;
        }

    </script>
</body>

</html>